home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / genial / func / zoom.c < prev   
Encoding:
C/C++ Source or Header  |  1992-07-14  |  13.6 KB  |  553 lines

  1. /*
  2.  * zoom.c -- function to zoom in on a rectangular region
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "display.h"
  7. #include "ui.h"
  8. #include "common.h"
  9. #include "log.h"
  10. #include "reg.h"
  11. #include "zoom_ui.h"
  12.  
  13. /* #define ZOOM_DEBUG */
  14.  
  15. GC        zgc;
  16. struct zcontext *zoom_by_lid(), *zoom_by_win(), *zoom_by_pwin();
  17.  
  18. /***********************************************************/
  19. zoom_init()
  20. {
  21.     setrtype(BOX);
  22.     reg_setdom(NONE);
  23.  
  24.     lab_info("Please select a rectangular region to zoom", 1);
  25.     lab_info("Hit <eval> when finished", 2);
  26.  
  27.     return 0;
  28. }
  29.  
  30. /***********************************************************/
  31. zoom_eval()
  32. {
  33.     struct zcontext *curzoom;
  34.  
  35. #ifdef ZOOM_DEBUG
  36.     printf("zoom eval \n");
  37. #endif
  38.  
  39.     curzoom = newzoom();
  40.     comp_zoom(curzoom);
  41.     draw_zoom(curzoom);
  42.     return 0;
  43. }
  44.  
  45. /***********************************************************/
  46. zoom_clear(id)
  47.     int       id;
  48. {
  49.     struct zcontext *zoom;
  50.  
  51.     zoom = zoom_by_lid(id);
  52.     if (zoom == NULL) {
  53.     fprintf(stderr, "zoom # %d not found \n", id);
  54.     return 0;
  55.     }
  56.     delzcontext(zoom);
  57.     return 0;
  58. }
  59.  
  60. /***************************************************************/
  61. struct zcontext *
  62. newzoom()
  63. {
  64.     struct zcontext *zoom;
  65.  
  66. #ifdef ZOOM_DEBUG
  67.     printf("newzoom\n");
  68. #endif
  69.  
  70.     if (curfunc->zoom != NULL)
  71.     free(curfunc->zoom);
  72.  
  73.     zoom_mk_cursors();
  74.     zoom = (struct zcontext *) malloc(sizeof(struct zcontext));
  75.     curfunc->zoom = zoom;
  76.     makezoom(zoom);
  77.     return zoom;
  78. }
  79.  
  80. /*******************************************************************/
  81. makezoom(zoom)
  82.     struct zcontext *zoom;
  83. {
  84.     XGCValues gcval;
  85.     char      title[80];
  86.     u_char   *zbuf;
  87.  
  88. #ifdef ZOOM_DEBUG
  89.     printf("makezoom \n");
  90. #endif
  91.  
  92.     zoom->display = zoom_zmwin_objects_initialize(NULL, base_win->ctrlwin);
  93.     zoom->paintwin = canvas_paint_window(zoom->display->zmcanv);
  94.     zoom->zxid = (XID) xv_get(zoom->paintwin, XV_XID, NULL);
  95.  
  96.     /* set up a GC for the window */
  97.     gcval.foreground = BlackPixel(display, DefaultScreen(display));
  98.     gcval.background = WhitePixel(display, DefaultScreen(display));
  99.     gcval.clip_mask = None;
  100.     zgc = XCreateGC(display, zoom->zxid,
  101.             GCForeground | GCBackground | GCClipMask, &gcval);
  102.  
  103.     zoom->zmfac = 2;
  104.  
  105.     if (curfunc->reg->r_plist->pt.x < curfunc->reg->r_plist->next->pt.x) {
  106.     zoom->p1.x = curfunc->reg->r_plist->pt.x;
  107.     zoom->p2.x = curfunc->reg->r_plist->next->pt.x;
  108.     } else {
  109.     zoom->p2.x = curfunc->reg->r_plist->pt.x;
  110.     zoom->p1.x = curfunc->reg->r_plist->next->pt.x;
  111.     }
  112.     if (curfunc->reg->r_plist->pt.y < curfunc->reg->r_plist->next->pt.y) {
  113.     zoom->p1.y = curfunc->reg->r_plist->pt.y;
  114.     zoom->p2.y = curfunc->reg->r_plist->next->pt.y;
  115.     } else {
  116.     zoom->p2.y = curfunc->reg->r_plist->pt.y;
  117.     zoom->p1.y = curfunc->reg->r_plist->next->pt.y;
  118.     }
  119.  
  120.     zoom->can_width = abs(zoom->p2.x - zoom->p1.x) * zoom->zmfac;
  121.     zoom->can_height = abs(zoom->p2.y - zoom->p1.y) * zoom->zmfac;
  122.  
  123. #ifdef ZOOM_DEBUG
  124.     printf("zooming window of size %d x %d \n",
  125.        abs(zoom->p2.x - zoom->p1.x), abs(zoom->p2.y - zoom->p1.y));
  126.     printf("zoom factor: %d \n", zoom->zmfac);
  127.     printf("creating zoom ximage: size %d x %d \n",
  128.        zoom->can_width, zoom->can_height);
  129. #endif
  130.  
  131.     switch (depth) {
  132.     case 8:
  133.     zbuf = (u_char *) malloc((unsigned) zoom->can_width * zoom->can_height);
  134.     zoom->zim = XCreateImage(display, winv, depth,
  135.                  ZPixmap, 0, zbuf, zoom->can_width,
  136.                  zoom->can_height, 8, 0);
  137.     break;
  138.     case 24:
  139.     case 32:
  140.     zbuf = (u_char *) malloc(zoom->can_width * zoom->can_height * 4);
  141.     zoom->zim = XCreateImage(display, winv, depth,
  142.                  ZPixmap, 0, zbuf, zoom->can_width,
  143.                  zoom->can_height, 32, 0);
  144.     break;
  145.     }
  146.     if (!zoom->zim) {
  147.     fprintf(stderr, "Error: couldn't create ximage!");
  148.     return (-1);
  149.     }
  150.     sprintf(title, "Zoom: %d", curfunc->id);
  151.     xv_set(zoom->display->zmwin, XV_LABEL, title, NULL);
  152.  
  153.     return (1);
  154. }
  155.  
  156. /********************************************************************/
  157. /* comp_zoom: actually do the zooming into the XImage structure */
  158. /* no, this isn't the most efficient implementation in the world, but we can
  159.    change that if we HAVE to (a faster method is to use bcopy to
  160.    replicate entire rows at a time)
  161.    */
  162. int
  163. comp_zoom(zoom)
  164.     struct zcontext *zoom;
  165. {
  166.     u_char   *zbuf;
  167.     u_long    v;
  168.     XPoint    p1, p2;
  169.     int       zmfac;
  170.     int       sx, ex, sy, ey;
  171.     register int i, j, x, y;
  172.     void      pixel_replicate();
  173.  
  174. #ifdef ZOOM_DEBUG
  175.     printf("comp_zoom \n");
  176. #endif
  177.  
  178.     set_watch_cursor();
  179.     p1.x = zoom->p1.x;
  180.     p1.y = zoom->p1.y;
  181.     p2.x = zoom->p2.x;
  182.     p2.y = zoom->p2.y;
  183.     zmfac = zoom->zmfac;
  184.  
  185.     if ((zoom->zim->width != zoom->can_width) ||
  186.     (zoom->zim->height != zoom->can_height)) {
  187.     free(zoom->zim->data);
  188.     XDestroyImage(zoom->zim);
  189.     zbuf = (u_char *) malloc((unsigned) zoom->can_width * zoom->can_height);
  190.     zoom->zim = XCreateImage(display, winv, depth,
  191.                  ZPixmap, 0, zbuf,
  192.                  zoom->can_width, zoom->can_height, 8, 0);
  193. #ifdef ZOOM_DEBUG
  194.     printf("re-creating zoom ximage: size %d x %d \n",
  195.            zoom->can_width, zoom->can_height);
  196. #endif
  197.     }
  198.     for (y = p1.y; y < p2.y; y++) {
  199.     for (x = p1.x; x < p2.x; x++) {
  200.         v = XGetPixel(orig_ximg, x, y);
  201.  
  202.         sy = (y - p1.y) * zmfac;
  203.         ey = sy + zmfac;
  204.         for (j = sy; j < ey; j++) {
  205.         sx = (x - p1.x) * zmfac;
  206.         ex = sx + zmfac;
  207.         for (i = sx; i < ex; i++) {
  208.             if (i >= zoom->can_width || j >= zoom->can_height) {
  209.             fprintf(stderr, "Error: invalid zoom window location \n");
  210.             return -1;
  211.             }
  212.             XPutPixel(zoom->zim, i, j, v);
  213.         }
  214.         }
  215.     }
  216.     }
  217.  
  218.     unset_watch_cursor();
  219.  
  220.     return 1;
  221. }
  222.  
  223. /*******************************************************************/
  224.  
  225. delzcontext(zoom)
  226.     struct zcontext *zoom;
  227. {
  228.     xv_set(zoom->display->zmwin,
  229.        XV_SHOW, FALSE,
  230.        NULL);
  231.     free(zoom->zim->data);
  232.     XDestroyImage(zoom->zim);
  233. }
  234.  
  235. /***********************************************************/
  236. struct zcontext *
  237. zoom_by_pwin(win)
  238.     Xv_Window win;
  239. {
  240.     struct zcontext *zoom;
  241.     struct logent *log;
  242.  
  243.     log = loghead;
  244.     while (log != NULL) {
  245.     zoom = log->zoom;
  246.     if (zoom != NULL) {
  247.         if (zoom->paintwin == win)
  248.         return zoom;
  249.     }
  250.     log = log->next;
  251.     }
  252.     return (NULL);
  253. }
  254.  
  255. /***********************************************************/
  256. struct zcontext *
  257. zoom_by_win(win)
  258.     Xv_Window win;
  259. {
  260.     struct zcontext *zoom;
  261.     struct logent *log;
  262.  
  263.     log = loghead;
  264.     while (log != NULL) {
  265.     zoom = log->zoom;
  266.     if (zoom != NULL) {
  267.         if (zoom->display->zmwin == win)
  268.         return zoom;
  269.     }
  270.     log = log->next;
  271.     }
  272.     return (NULL);
  273. }
  274.  
  275. /*****************************************************************/
  276. struct zcontext *
  277. zoom_by_lid(id)
  278.     int       id;
  279. {
  280.     struct logent *log;
  281.  
  282.     log = loghead;
  283.     while (log != NULL) {
  284.     if (log->id == id)
  285.         return (log->zoom);
  286.     log = log->next;
  287.     }
  288.     fprintf(stderr, "zoom_by_lid: not found \n");
  289.     return NULL;
  290. }
  291.  
  292. /***********************************************************/
  293. draw_zoom(zoom)
  294.     struct zcontext *zoom;
  295. {
  296.     void      zmcanv_repaint_proc();
  297.  
  298. #ifdef ZOOM_DEBUG
  299.     printf("draw_zoom \n");
  300. #endif
  301.  
  302.     set_watch_cursor();
  303.     xv_set(zoom->display->zmwin,
  304.        XV_SHOW, TRUE, FRAME_CLOSED, FALSE, NULL);
  305.  
  306.     xv_set(zoom->display->zmwin,
  307.        XV_WIDTH, MIN((zoom->can_width + SCROLL_BAR_SIZE), 512),
  308.        XV_HEIGHT, MIN((zoom->can_height + SCROLL_BAR_SIZE), 512),
  309.        NULL);
  310.  
  311.     xv_set(zoom->display->zmcanv,
  312.        CANVAS_AUTO_SHRINK, FALSE,
  313.        CANVAS_AUTO_EXPAND, FALSE,
  314.        OPENWIN_AUTO_CLEAR, TRUE,
  315.        CANVAS_FIXED_IMAGE, FALSE,
  316.        NULL);
  317.  
  318.     xv_set(zoom->display->zmcanv,
  319.        CANVAS_WIDTH, zoom->can_width,
  320.        CANVAS_HEIGHT, zoom->can_height,
  321.        NULL);
  322.  
  323. #ifdef ZOOM_DEBUG
  324.     printf("set window size: %dx%d \n",
  325.        MIN((zoom->can_width + SCROLL_BAR_SIZE), 512),
  326.        MIN((zoom->can_height + SCROLL_BAR_SIZE), 512));
  327.     printf("set canvas size: %dx%d \n", zoom->can_width, zoom->can_height);
  328. #endif
  329.  
  330.     zmcanv_repaint_proc(zoom->display->zmcanv, zoom->paintwin,
  331.             display, zoom->zxid, NULL);
  332.     unset_watch_cursor();
  333. }
  334.  
  335. /***************************************************************/
  336. /*
  337.  * Repaint callback function for `zmcanv'.
  338.  */
  339. void
  340. zmcanv_repaint_proc(canvas, paint_window, display, xid, rects)
  341.     Canvas    canvas;
  342.     Xv_window paint_window;
  343.     Display  *display;
  344.     Window    xid;
  345.     Xv_xrectlist *rects;
  346. {
  347.     struct zcontext *zoom;
  348.  
  349.     zoom = zoom_by_pwin(paint_window);
  350.     if (zoom == NULL || zoom->zim == NULL) {
  351.     return;
  352.     }
  353. #ifdef ZOOM_DEBUG
  354.     printf("zoom_repaint_proc: putimage size; %d x %d \n", zoom->can_width,
  355.        zoom->can_height);
  356. #endif
  357.  
  358.     XPutImage(display, xid, zgc, zoom->zim, 0, 0, 0, 0,
  359.           zoom->can_width, zoom->can_height);
  360. }
  361.  
  362. /**************************************************************/
  363. void
  364. zoom_resize_proc(win, event, arg, type)
  365.     Xv_window win;
  366.     Event    *event;
  367.     Notify_arg arg;
  368.     Notify_event_type type;
  369. {
  370.     struct zcontext *zoom;
  371.     int       width, height;
  372.  
  373.     if (logtail == NULL)
  374.     return;
  375.  
  376.     if ((zoom = zoom_by_win(win)) == NULL) {
  377.     return;
  378.     }
  379. #ifdef ZOOM_DEBUG
  380.     fprintf(stderr, "genial: got zoom resize event \n");
  381. #endif
  382.  
  383.     width = (int) xv_get(zoom->display->zmwin, XV_WIDTH, NULL);
  384.     height = (int) xv_get(zoom->display->zmwin, XV_HEIGHT, NULL);
  385.  
  386.     if (width > zoom->can_width + SCROLL_BAR_SIZE) {
  387.     xv_set(zoom->display->zmwin,
  388.            XV_WIDTH, zoom->can_width + SCROLL_BAR_SIZE, NULL);
  389.     }
  390.     if (height > zoom->can_height + SCROLL_BAR_SIZE) {
  391.     xv_set(zoom->display->zmwin,
  392.            XV_HEIGHT, zoom->can_height + SCROLL_BAR_SIZE, NULL);
  393.     }
  394.     return;
  395. }
  396.  
  397. /***********************************************************************/
  398. Notify_value
  399. zmcanv_event_proc(win, event, arg, type)
  400.     Xv_window win;
  401.     Event    *event;
  402.     Notify_arg arg;
  403.     Notify_event_type type;
  404. {
  405.     struct zcontext *zoom;
  406.     int       x, y, dir;
  407.  
  408.     if ((zoom = zoom_by_pwin(win)) == NULL) {
  409.     fprintf(stderr, "zoom_event_prov: win not found \n");
  410.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  411.     }
  412.  
  413.     x = event_x(event);
  414.     y = event_y(event);
  415.     /* which direction is the user heading */
  416.     dir = direction(x, y, zoom);
  417.     /* make the cursor reflect that */
  418.     setcursor(win, dir);
  419.  
  420.    /* middle button = pan */
  421.     if (event_is_down(event) && event_id(event) == BUT(2)) {
  422.     /*
  423.      * move in that direction if possible
  424.      */
  425.     zoom_xlate(zoom, x, y, dir);
  426.     draw_zoom(zoom);
  427.     }
  428.  
  429.     /* left button = zoom in */
  430.     if (event_is_down(event) && event_id(event) == BUT(1)) {
  431.     /*
  432.      * double the scale factor, keep region size same
  433.      */
  434.     if (zoom->zmfac >= 8)
  435.         return notify_next_event_func(win, (Notify_event) event, arg, type);
  436.  
  437.     zoom->zmfac++;
  438.     zoom->can_width = abs(zoom->p2.x - zoom->p1.x) * zoom->zmfac;
  439.     zoom->can_height = abs(zoom->p2.y - zoom->p1.y) * zoom->zmfac;
  440.  
  441.     comp_zoom(zoom);
  442.     draw_zoom(zoom);
  443.     }
  444.  
  445.     /* right button = zoom out */
  446.     if (event_is_down(event) && event_id(event) == BUT(3)) {
  447.     /*
  448.      * halve the scale factor, keep region size same
  449.      */
  450.     if (zoom->zmfac <= 1)
  451.         return notify_next_event_func(win, (Notify_event) event, arg, type);
  452.  
  453.     zoom->zmfac--;
  454.     zoom->can_width = abs(zoom->p2.x - zoom->p1.x) * zoom->zmfac;
  455.     zoom->can_height = abs(zoom->p2.y - zoom->p1.y) * zoom->zmfac;
  456.  
  457.     comp_zoom(zoom);
  458.     draw_zoom(zoom);
  459.     }
  460.     return notify_next_event_func(win, (Notify_event) event, arg, type);
  461. }
  462.  
  463. /*****************************************************************/
  464. /* routine to translate zoom to (x,y) in the direction specified */
  465. zoom_xlate(zoom, x, y, dir)
  466.     struct zcontext *zoom;
  467.     int       x, y, dir;
  468. {
  469.     int       cx, cy, width, height;
  470.     int       box_width, box_height;
  471.     struct region *treg;    /* temporary region */
  472.  
  473.     width = (int) xv_get(zoom->display->zmwin, XV_WIDTH, NULL);
  474.     height = (int) xv_get(zoom->display->zmwin, XV_HEIGHT, NULL);
  475.  
  476.     box_width = abs(zoom->p2.x - zoom->p1.x);
  477.     box_height = abs(zoom->p2.y - zoom->p1.y);
  478.  
  479.     cx = x - width / 2;
  480.     cy = y - height / 2;
  481.     treg = newreg(BOX);
  482.     if ((dir == LEFT) || (dir == RIGHT)) {
  483.     zoom->p1.x += cx;
  484.     zoom->p2.x = zoom->p1.x + box_width;
  485.     } else {
  486.     zoom->p1.y += cy;
  487.     zoom->p2.y = zoom->p1.y + box_height;
  488.     }
  489.     /* make sure the numbers here are within reasonable bounds */
  490.     zoom_bound(zoom, box_width, box_height);
  491.  
  492.     reg_addpt(treg, zoom->p1.x, zoom->p1.y);
  493.     reg_addpt(treg, zoom->p2.x, zoom->p2.y);
  494.     draw_box(treg);
  495.     log_chreg(curfunc->prev->id, treg);
  496.     comp_zoom(zoom);
  497.     draw_zoom(zoom);
  498. }
  499.  
  500. /*****************************************************************/
  501. /* direction returns the direction the user is heading in the most */
  502. int
  503. direction(x, y, zoom)
  504.     int       x, y;
  505.     struct zcontext *zoom;
  506. {
  507.     int       cx, cy;        /* x and y in coordinate form */
  508.     int       width, height;
  509.  
  510.     width = (int) xv_get(zoom->display->zmwin, XV_WIDTH, NULL);
  511.     height = (int) xv_get(zoom->display->zmwin, XV_HEIGHT, NULL);
  512.  
  513.     cx = x - width / 2;
  514.     cy = y - height / 2;
  515.     if (abs(cx) > abs(cy)) {
  516.     return ((cx > 0) ? RIGHT : LEFT);
  517.     } else
  518.     return ((cy > 0) ? DOWN : UP);
  519. }
  520.  
  521. /*****************************************************************/
  522. /* zoom_bound() makes sure that p1 and p2 members of the zoom structure are
  523. within reasonable bounds
  524. */
  525.  
  526. zoom_bound(zoom, box_width, box_height)
  527.     struct zcontext *zoom;
  528.     int       box_width, box_height;
  529. {
  530.  
  531.     box_width = abs(zoom->p2.x - zoom->p1.x);
  532.     box_height = abs(zoom->p2.y - zoom->p1.y);
  533.  
  534.     /* if p1 is < 0, shift the whole region forward */
  535.     if (zoom->p1.x < 0) {
  536.     zoom->p1.x = 0;
  537.     zoom->p2.x = box_width;
  538.     }
  539.     if (zoom->p1.y < 0) {
  540.     zoom->p1.y = 0;
  541.     zoom->p2.y = box_height;
  542.     }
  543.     /* if p2 is past the edge of the image, shift the whole region back */
  544.     if (zoom->p2.x > orig_ximg->width) {
  545.     zoom->p1.x = orig_ximg->width - box_width;
  546.     zoom->p2.x = orig_ximg->width;
  547.     }
  548.     if (zoom->p2.y > orig_ximg->height) {
  549.     zoom->p1.y = orig_ximg->height - box_height;
  550.     zoom->p2.y = orig_ximg->height;
  551.     }
  552. }
  553.